# -*- coding: UTF-8 -*-
import time
import datetime
import logging
import sqlalchemy
import requests
import tushare as ts
from wxpy import *

# 配置日志
logging.basicConfig(filename='wx_scrt.log', level=logging.INFO,
                    format='%(asctime)s %(levelname)s:%(message)s')


def init_finance_api():
    ts.set_token('7d6536b049aaa9fba265a5dc350c84dbb8e3293fb53af223fc1600dc')
    pro = ts.pro_api()
    logging.info(u'初始化金融数据接口成功')
    return pro


def init_wechat_bot():
    bot = Bot(console_qr=True)
    bot.join()
    # embed()
    return bot


class Secretary:
    def __init__(self, gap_time=900):
        self.pro = init_finance_api()
        self.bot = init_wechat_bot()
        self.gap_time = gap_time
        self.s2n_url = 'https://emdatah5.eastmoney.com/dc/HSGTN/GetHSGTRtminData'
        self.s2n_params = {
            'fields1': 'f1,f2,f3,f4',
            'fields2': 'f51,f52,f53,f54,f55,f56',
            'ut': None
        }

    # 心跳通信
    def heart_beat(self, endtime):
        try:
            while True:
                delta = datetime.datetime.strptime(
                    endtime, '%Y%m%d %H:%M:%S') - datetime.datetime.now()
                if delta.total_seconds() > 0:   # 未到结束时间，定时发送心跳消息
                    self.bot.groups(update=True, contact_only=True)
                    logging.info(u'心跳正常，账户登录正常，休眠：' + str(self.gap_time) + '秒')
                    time.sleep(self.gap_time)
                else:   # 已到结束时间
                    logging.info(u'结束心跳')
                    break
        except ResponseError as e:
            if e.err_code == '1205':
                logging.warn(u'访问过于频繁，尝试增加休眠时间')
                time.sleep(1800)
            if e.err_code == '1100' or '1101' or '1102':
                logging.warn(u'微信已掉线，尝试重新登录')
                self.bot = init_wechat_bot()

    # 判断今日是否为交易日，返回1：是 | 0：否

    def check_deal_or_not(self, date=datetime.date.today().strftime('%Y%m%d')):
        return self.pro.trade_cal(start_date=date, end_date=date)['is_open'].values[0]

    # 计算下一交易日的时间
    def next_trade_time(self, this_datetime):
        next_day_time = this_datetime + datetime.timedelta(days=1)
        next_day_time_str = next_day_time.strftime('%Y%m%d')
        while True:
            # if self.pro.trade_cal(start_date=next_day_time_str, end_date=next_day_time_str)['is_open'].values[0] == 1:
            if self.check_deal_or_not(next_day_time_str) == 1:
                next_day_time_str = next_day_time_str + ' 09:30:00'
                return next_day_time_str
            else:
                next_day_time = datetime.date.today() + datetime.timedelta(days=1)
                next_day_time_str = next_day_time.strftime('%Y%m%d')

    # 获取北向资金数据
    def s2n_data(self, tick='all'):
        try:
            if tick == 'all':
                return requests.get(url=self.s2n_url, params=self.s2n_params).json()['data']['s2n']
            else:
                all_data = requests.get(url=self.s2n_url, params=self.s2n_params).json()[
                    'data']['s2n']
                hours, minutes = tick.split(':')
                hours = int(hours)
                minutes = int(minutes)
                if 9 <= hours <= 11:
                    start_time = datetime.datetime.strptime('09:30', '%H:%M')
                    tick_time = datetime.datetime.strptime(tick, '%H:%M')
                    tick_index = int((tick_time - start_time).seconds/60)
                    return all_data[tick_index]
                elif 13 <= hours <= 15:
                    start_time = datetime.datetime.strptime('13:00', '%H:%M')
                    tick_time = datetime.datetime.strptime(tick, '%H:%M')
                    tick_index = int((tick_time - start_time).seconds/60) + 120
                    return all_data[tick_index]
                else:
                    logging.error(u'非交易时段')
        except:
            logging.error(u'获取北向资金错误')
            return 'error'

    # 生成每日北向资金日报
    def create_s2n_report(self, report_tick='15:00'):
        final_s2n_data = self.s2n_data(tick=report_tick).split(',')
        tick = final_s2n_data[0]    # 时刻
        hgt_in = '%.2f' % (float(final_s2n_data[1])/10000)  # 沪股通当日净流入(亿元)
        # hgt_balances = final_s2n_data[2]    # 沪股通当日余额(万元)
        sgt_in = '%.2f' % (float(final_s2n_data[3])/10000)  # 深股通当日净流入(亿元)
        # sgt_balances = final_s2n_data[4]    # 深股通当日余额(万元)
        s2n_in = '%.2f' % (float(final_s2n_data[5])/10000)    # 北向资金当日净流入(亿元)

        report = u'截止今日' + tick + u'时\n北向资金净流入：' + \
            s2n_in + u'亿元。\n其中沪股通：' + hgt_in + u'亿元，深股通：' + sgt_in + u'亿元'

        self.bot.file_helper.send(report)

    
    # 运行方法
    def run(self):
        while True:
            now_datetime = datetime.datetime.now()
            # 今日为非交易日，进行心跳连接，防止掉线
            if self.check_deal_or_not() == 0:
                # 计算下一交易日的时间
                next_day_time_str = self.next_trade_time(now_datetime)
                logging.info(u'今日为非交易日，下一交易日时间为' + next_day_time_str)
                # 进行心跳连接
                self.heart_beat(endtime=next_day_time_str)
            else:
                # 初始化数据
                # s2n_data = None
                # 今日为交易日获取当前时间
                now_time = now_datetime.strftime('%H:%M')
                start_trade_time = datetime.date.today()
                start_trade_time_str = start_trade_time.strftime(
                        '%Y%m%d') + ' 09:30:00'
                if now_time < '09:30':
                    logging.info(u'当前未开盘')
                    self.heart_beat(endtime=start_trade_time_str)
                elif '11:30' <= now_time <= '13:00':
                    logging.info(u'当前为1130-1300非交易时段')
                    if now_time == '11:30':
                        self.create_s2n_report(report_tick='11:30')
                    start_trade_time_str = start_trade_time.strftime(
                        '%Y%m%d') + ' 13:00:00'
                    self.heart_beat(endtime=start_trade_time_str)
                elif '09:30' < now_time < '11:30' or '13:00' < now_time <= '15:00':
                    logging.info(u'当前为交易时段')
                    if now_time == '10:00' or '11:00' or '14:00' or '15:00':
                        self.create_s2n_report(report_tick=now_time)
                    logging.info(u'休眠15分钟')
                    time.sleep(900)
                    pass
                else:
                    # 当天交易时段结束，20:00生成北向资金每日日报
                    logging.info(u'当前已休盘')
                    if now_time == '20:00':
                        self.create_s2n_report()
                    # 计算下一交易日的时间
                    next_day_time_str = self.next_trade_time(now_datetime)
                    logging.info(u'今日已休盘，下一交易日时间为' + next_day_time_str)
                    # 进行心跳连接
                    self.heart_beat(endtime=next_day_time_str)


if __name__ == '__main__':
    my_scrt = Secretary()
    my_scrt.run()
